package com.swak.reactivex.p2p.exchange;

import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.swak.exception.RemotingException;
import com.swak.reactivex.p2p.Group;
import com.swak.reactivex.p2p.Peer;
import com.swak.reactivex.p2p.PeerID;
import com.swak.reactivex.transport.ExchangeChannel;
import com.swak.reactivex.transport.ExchangeClient;
import com.swak.reactivex.transport.ExchangeServer;
import com.swak.registry.URL;

/**
 * ExchangePeer.
 * 
 * @author 618lf
 */
@Deprecated
public class ExchangePeer implements Peer {

	private static final Logger logger = LoggerFactory.getLogger(ExchangePeer.class);
	private final PeerID peerID;
	private final ExchangeGroup group;

	/**
	 * server 和 clients 都持有一部分的连接
	 */
	private final ExchangeServer server;
	private final Map<URL, ExchangeClient> clients;

	/**
	 * 真正的所有的连接：连接我的，我连接其他人的
	 */
	private final ExchangeChannels channels;

	public ExchangePeer(PeerID peerID, ExchangeGroup group, ExchangeServer server, Map<URL, ExchangeClient> clients,
			ExchangeChannels channels) {
		this.peerID = peerID;
		this.group = group;
		this.server = server;
		this.clients = clients;
		this.channels = channels;
	}

	@Override
	public PeerID peerID() {
		return peerID;
	}

	@Override
	public Set<PeerID> peers() {
		return channels.peers();
	}

	@Override
	public void leave() throws RemotingException {
		group.leave(server.url());
	}

	@Override
	public void close() {
		try {
			leave();
		} catch (RemotingException e) {
			logger.error(e.getMessage(), e);
		}
	}

	@Override
	public Group group() {
		return this.group;
	}

	@Override
	public ExchangeChannel lookup(PeerID peerID) {
		return channels.get(peerID);
	}

	@Override
	public void send(Object message) throws RemotingException {
		send(message, false);
	}

	@Override
	public void send(Object message, boolean sent) throws RemotingException {
		Throwable last = null;
		try {
			this.server.send(message, sent);
		} catch (Throwable t) {
			last = t;
		}
		for (ExchangeClient client : clients.values()) {
			try {
				client.send(message, sent);
			} catch (Throwable t) {
				last = t;
			}
		}
		if (last != null) {
			if (last instanceof RemotingException) {
				throw (RemotingException) last;
			} else if (last instanceof RuntimeException) {
				throw (RuntimeException) last;
			} else {
				throw new RuntimeException(last.getMessage(), last);
			}
		}
	}
}
